#lang errortrace racket
(require "hw5-util.rkt")
#|
(parse-frame
    '[ E10 (a . 10)
       (b . (closure E0 (lambda (y) a)))])
|#
;-----------------

; (struct frame (parent locals) #:transparent)


; ; Example 1:
; ; E0: [
; ;   (x . 3)
; ;   (y . 5)
; ; ]
; (define f1 (frame #f
;   (hash
;     (d:variable 'x) (d:number 3)
;     (d:variable 'y) (d:number 5))))

; #|
; E1:  [ E0
;   (z . 6)
;   (x . 7)
; ]
; |#
; (define f2
;   (frame (handle 0)
;     (hash
;       (d:variable 'z) (d:number 6)
;       (d:variable 'x) (d:number 7))))


(require rackunit)

; (closure E0 (lambda (y) a)
(define c (d:closure (handle 0) (d:lambda (list (d:variable 'y)) (d:variable 'a))))
;E0: [
;  (a . 20)
;  (b . (closure E0 (lambda (y) a)))
;]
(define f1
  (frame-put
    (frame-put root-frame (d:variable 'a) (d:number 10))
    (d:variable 'b) c))

(check-equal? f1 (frame #f (hash (d:variable 'a) (d:number 10)
   (d:variable 'b) c)))

; Lookup a
(define (frame-get f x)
  (define locals (frame-locals f))
  (hash-ref locals x))

(check-equal? (d:number 10) (frame-get f1 (d:variable 'a)))

(define (frame-push parent k v)
  (frame parent (hash k v)))

(define f3 (frame-push (handle 0) (d:variable 'x) (d:number 99)))

(define (frame-put:2 f k v)
  (define old-locals (frame-locals f))
  (define new-locals (hash-set old-locals k v))
  (frame (frame-parent f) new-locals))

(frame-put:2 f3 (d:variable 'x) (d:number 0))

; Lookup b
; (check-equal? c (frame-get f1 (d:variable 'b)))
; ; Lookup c that does not exist
; (check-equal? #f (frame-get f1 (d:variable 'c)))




;